#include "snake.h"
#include <iostream>
#include <chrono>
#include <thread>

#ifdef _WIN32
#include <conio.h>
#else
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#endif

using namespace std;
using namespace Snake;

// Simple cross-platform input handling
int getKeyPress() {
#ifdef _WIN32
    if (_kbhit()) {
        return _getch();
    }
    return -1;
#else
    struct termios oldt, newt;
    int ch;
    int oldf;

    tcgetattr(STDIN_FILENO, &oldt);
    newt = oldt;
    newt.c_lflag &= ~(ICANON | ECHO);
    tcsetattr(STDIN_FILENO, TCSANOW, &newt);
    oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
    fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);

    ch = getchar();

    tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
    fcntl(STDIN_FILENO, F_SETFL, oldf);

    return ch;
#endif
}

int main() {
    try {
        GameController game;
        bool running = true;
        
        cout << "Snake Game - Controls:" << endl;
        cout << "  W - Move Up" << endl;
        cout << "  S - Move Down" << endl;
        cout << "  A - Move Left" << endl;
        cout << "  D - Move Right" << endl;
        cout << "  R - Restart Game" << endl;
        cout << "  Q - Quit Game" << endl << endl;
        
        cout << "Press any key to start...";
        getKeyPress();
        
        // Initial render
        game.render();
        
        while (running) {
            // Wait for user input
            int key = getKeyPress();
            if (key == -1) {
                // No input, continue waiting
                std::this_thread::sleep_for(std::chrono::milliseconds(50)); // 50ms delay
                continue;
            }
            
            if (key == 'q' || key == 'Q') {
                running = false;
            } else {
                game.processInput(static_cast<char>(key));
                // Update and render only when a valid movement key is pressed
                if (key == 'w' || key == 's' || key == 'a' || key == 'd' || key == 'r') {
                    game.update();
                    game.render();
                }
            }
        }
        
        cout << "Game exited. Thanks for playing!" << endl;
    } catch (SnakeException& e) {
        cerr << "Snake Exception: " << e.getInfo() << endl;
        return 1;
    } 
    
    return 0;
}

